package com.xyz.xservice.modules.demo.util;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;

public class DateUtil {


	/** 毫秒 */
	public final static long MS = 1;
	/** 每秒钟的毫秒数 */
	public final static long SECOND_MS = MS * 1000;
	/** 每分钟的毫秒数 */
	public final static long MINUTE_MS = SECOND_MS * 60;
	/** 每小时的毫秒数 */
	public final static long HOUR_MS = MINUTE_MS * 60;
	/** 每天的毫秒数 */
	public final static long DAY_MS = HOUR_MS * 24;

	/** 标准日期格式 */
	public final static String NORM_DATE_PATTERN = "yyyy-MM-dd";
	/** 标准时间格式 */
	public final static String NORM_TIME_PATTERN = "HH:mm:ss";
	/** 标准日期时间格式 */
	public final static String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
	/** 斜杠日期时间格式 */
	public final static String NORM_DATETIME_SLASH_PATTERN = "yyyy/MM/dd HH:mm:ss";
	/** HTTP头中日期时间格式 */
	public final static String HTTP_DATETIME_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z";
	/** 导出文件命名后缀日期格式 */
	public final static String EXPORT_DATETIME_PATTERN = "yyyyMMddHHmmss";
	/** 日期间隔格式 */
	public final static String DATE_INTERVAL__PATTERN="yyyy年mm个月dd天";

	//Sonar updates
	/** 标准日期（不含时间）格式化器 *//*
	private final static SimpleDateFormat NORM_DATE_FORMAT = new SimpleDateFormat(NORM_DATE_PATTERN);
	*//** 标准时间格式化器 *//*
	private final static SimpleDateFormat NORM_TIME_FORMAT = new SimpleDateFormat(NORM_TIME_PATTERN);
	*//** 标准日期时间格式化器 *//*
	private final static SimpleDateFormat NORM_DATETIME_FORMAT = new SimpleDateFormat(NORM_DATETIME_PATTERN);
	*//** 斜杠日期时间格式化器 *//*
	private final static SimpleDateFormat NORM_DATETIME_SLASH_FORMAT = new SimpleDateFormat(NORM_DATETIME_SLASH_PATTERN);
	*//** HTTP日期时间格式化器 *//*
	private final static SimpleDateFormat HTTP_DATETIME_FORMAT = new SimpleDateFormat(HTTP_DATETIME_PATTERN, Locale.US);*/

	public static final String[] patterns = {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd","yyyy/MM/dd HH:mm:ss"};
	/**
	 * 当前时间，格式 yyyy-MM-dd HH:mm:ss
	 * @return 当前时间的标准形式字符串
	 */
	public static String now() {
		return formatDateTime(new Date());
	}

	/**
	 * 当前日期，格式 yyyy-MM-dd
	 * @return 当前日期的标准形式字符串
	 */
	public static String today() {
		return formatDate(new Date());
	}

	// ------------------------------------ Format start ----------------------------------------------
	/**
	 * 根据特定格式格式化日期
	 * @param date 被格式化的日期
	 * @param format 格式
	 * @return 格式化后的字符串
	 */
	public static String format(Date date, String format){
		return new SimpleDateFormat(format).format(date);
	}

	/**
	 * 格式 yyyy-MM-dd HH:mm:ss
	 * @param date 被格式化的日期
	 * @return 格式化后的日期
	 */
	public static String formatDateTime(Date date) {

		return new SimpleDateFormat(NORM_DATETIME_PATTERN).format(date);
	}

	/**
	 * 格式 yyyy/MM/dd HH:mm:ss
	 * @param date 被格式化的日期
	 * @return 格式化后的日期
	 */
	public static String formatSlashDateTime(Date date) {

		return new SimpleDateFormat(NORM_DATETIME_SLASH_PATTERN).format(date);
	}

	/**
	 * 格式化为Http的标准日期格式
	 * @param date 被格式化的日期
	 * @return HTTP标准形式日期字符串
	 */
	public static String formatHttpDate(Date date) {
//			return new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US).format(date);
		return new SimpleDateFormat(NORM_DATETIME_PATTERN).format(date);
	}

	/**
	 * 格式 yyyy-MM-dd
	 * @param date 被格式化的日期
	 * @return 格式化后的字符串
	 */
	public static String formatDate(Date date) {
//			return format(d, "yyyy-MM-dd");
		return new SimpleDateFormat(NORM_DATE_PATTERN).format(date);
	}
	// ------------------------------------ Format end ----------------------------------------------


	// ------------------------------------ Parse start ----------------------------------------------
	/**
	 * 将特定格式的日期转换为Date对象
	 * @param dateString 特定格式的日期
	 * @param format 格式，例如yyyy-MM-dd
	 * @return 日期对象
	 */
	public static Date parse(String dateString, String format){
		try {
			return (new SimpleDateFormat(format)).parse(dateString);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 格式yyyy-MM-dd HH:mm:ss
	 * @param dateString 标准形式的时间字符串
	 * @return 日期对象
	 */
	public static Date parseDateTime(String dateString){
//			return parse(s, "yyyy-MM-dd HH:mm:ss");
		try {
			return new SimpleDateFormat(NORM_DATETIME_PATTERN).parse(dateString);
		} catch (ParseException e) {
			//log.error("Parse " + dateString + " with format " + NORM_DATETIME_FORMAT.toPattern() + " error!", e);
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 格式yyyy-MM-dd
	 * @param dateString 标准形式的日期字符串
	 * @return 日期对象
	 */
	public static Date parseDate(String dateString){
		try {
			return new SimpleDateFormat(NORM_DATE_PATTERN).parse(dateString);
		} catch (ParseException e) {
			//log.error("Parse " + dateString + " with format " + NORM_DATE_PATTERN + " error!", e);
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 格式HH:mm:ss
	 * @param timeString 标准形式的日期字符串
	 * @return 日期对象
	 */
	public static Date parseTime(String timeString){
		try {
			return new SimpleDateFormat(NORM_TIME_PATTERN).parse(timeString);
		} catch (ParseException e) {
			//log.error("Parse " + timeString + " with format " + NORM_TIME_PATTERN + " error!", e);
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 格式：<br>
	 * 1、yyyy-MM-dd HH:mm:ss<br>
	 * 2、yyyy-MM-dd<br>
	 * 3、HH:mm:ss>
	 * @param dateStr 日期字符串
	 * @return 日期
	 */
	public static Date parse(String dateStr) {
		int length = dateStr.length();
		try {
			if(length == DateUtil.NORM_DATETIME_PATTERN.length()) {
				return parseDateTime(dateStr);
			}else if(length == DateUtil.NORM_DATE_PATTERN.length()) {
				return parseDate(dateStr);
			}else if(length == DateUtil.NORM_TIME_PATTERN.length()){
				return parseTime(dateStr);
			}
		}catch(Exception e) {
			//log.error("Parse " + dateStr + " with format normal error!", e);
			e.printStackTrace();
		}
		return null;
	}
	// ------------------------------------ Parse end ----------------------------------------------



	// ------------------------------------ Offset start ----------------------------------------------

	/**
	 * 昨天
	 * @return 昨天
	 */
	public static Date yesterday() {
		return offsiteDate(new Date(), Calendar.DAY_OF_YEAR, -1);
	}

	/**
	 * 上周
	 * @return 上周
	 */
	public static Date lastWeek() {
		return offsiteDate(new Date(), Calendar.WEEK_OF_YEAR, -1);
	}

	/**
	 * 上个月
	 * @return 上个月
	 */
	public static Date lastMouth() {
		return offsiteDate(new Date(), Calendar.MONTH, -1);
	}

	/**
	 * 获取指定日期偏移指定时间后的时间
	 * @param date 基准日期
	 * @param calendarField 偏移的粒度大小（小时、天、月等）使用Calendar中的常数
	 * @param offsite 偏移量，正数为向后偏移，负数为向前偏移
	 * @return 偏移后的日期
	 */
	public static Date offsiteDate(Date date, int calendarField, int offsite){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(calendarField, offsite);
		return cal.getTime();
	}
	// ------------------------------------ Offset end ----------------------------------------------



	/**
	 * 判断两个日期相差的时长<br/>
	 * 返回 minuend - subtrahend 的差
	 * @param subtrahend 减数日期
	 * @param minuend 被减数日期
	 * @param diffField 相差的选项：相差的天、小时
	 * @return 日期差
	 */
	public static long diff(Date subtrahend, Date minuend, long diffField){
		long diff = minuend.getTime() - subtrahend.getTime();
		return diff/diffField;
	}

	/**
	 * 计时，常用于记录某段代码的执行时间，单位：纳秒
	 * @param preTime 之前记录的时间
	 * @return 时间差，纳秒
	 */
	public static long spendNt(long preTime) {
		return System.nanoTime() - preTime;
	}

	/**
	 * 计时，常用于记录某段代码的执行时间，单位：毫秒
	 * @param preTime 之前记录的时间
	 * @return 时间差，毫秒
	 */
	public static long spendMs(long preTime) {
		return System.currentTimeMillis() - preTime;
	}


	/**
	 * 根据出生日期自动计算年龄
	 * @param birthDate 出生日期
	 * @return
	 */
	public static Integer getAgeByBirth(Date birthDate) throws ParseException{
		int age = 0;
		Calendar cal = Calendar.getInstance();
		if (cal.before(birthDate)) { //出生日期晚于当前时间，无法计算
			throw new IllegalArgumentException(
					"The Day is before Now.It's unbelievable!");
		}
		int yearNow = cal.get(Calendar.YEAR);  //当前年份
		int monthNow = cal.get(Calendar.MONTH);  //当前月份
		int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); //当前日期
		cal.setTime(birthDate);
		int yearBirth = cal.get(Calendar.YEAR);
		int monthBirth = cal.get(Calendar.MONTH);
		int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
		age = yearNow - yearBirth;   //计算整岁数
		if (monthNow <= monthBirth) {
			if (monthNow == monthBirth) {
				if (dayOfMonthNow < dayOfMonthBirth) {age--;}//当前日期在生日之前，年龄减一
			} else {
				age--;//当前月份在生日之前，年龄减一
			}
		}
		return age;
	}

	/**
	 * 获取当前月份的第一天
	 */
	public static Date getCurrentMonthFirstDay(){
		LocalDate now = LocalDate.now();
		LocalDate firstDay = now.with(TemporalAdjusters.firstDayOfMonth());
		return Date.from(firstDay.atStartOfDay(ZoneOffset.ofHours(8)).toInstant());
	}

	/**
	 * 获取当前月份最后一天
	 */
	public static Date getCurrentMonthEndDay(){
		LocalDate now = LocalDate.now();
		LocalDate lastDay = now.with(TemporalAdjusters.lastDayOfMonth());
		Date endTime = Date.from(lastDay.atStartOfDay(ZoneOffset.ofHours(8)).toInstant());
		SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
		try {
			return format.parse(new SimpleDateFormat("yyyyMMdd").format(endTime) + " 23:59:59");
		} catch (ParseException e) {
			e.printStackTrace();
		}
		throw new IllegalArgumentException("时间格式转换错误");
	}

	/**
	 *获取今天的开始时间
	 */
	public static Date getDayStartTime(Date date){
		Calendar startTime = Calendar.getInstance();
		startTime.setTime(date);
		startTime.set(Calendar.HOUR_OF_DAY, 0);
		startTime.set(Calendar.MINUTE, 0);
		startTime.set(Calendar.SECOND, 0);
		return startTime.getTime();
	}

	/**
	 *获取今天的结束时间
	 */
	public static Date getDayEndTime(Date date){
		Calendar endTime = Calendar.getInstance();
		endTime.setTime(date);
		endTime.set(Calendar.HOUR_OF_DAY, 23);
		endTime.set(Calendar.MINUTE, 59);
		endTime.set(Calendar.SECOND, 59);
		return endTime.getTime();
	}


	/**
	 * 获取本周的开始时间
	 */
	public static Date getWeekStartTime(){
		Date date = new Date();
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
		if (dayofweek == 1) {
			dayofweek += 7;
		}
		cal.add(Calendar.DATE, 2 - dayofweek);
		return getDayStartTime(cal.getTime());

	}

	/**
	 * 获取本周的结束时间
	 */
	public static Date getWeekEndTime(){
		Calendar cal = Calendar.getInstance();
		cal.setTime(getWeekStartTime());
		cal.add(Calendar.DAY_OF_WEEK, 6);
		Date weekEndSta = cal.getTime();
		return getDayEndTime(weekEndSta);

	}

	/**
	 * 获取当前过去多少天时间
	 * @param date
	 * @return
	 */
	public static Date getPastTime(int date){
		return offsiteDate(new Date(), Calendar.DAY_OF_YEAR, -date);
	}
	/**
	 * 获取月份最后一天
	 */
	public static Date getCurrentMonthEndDay(Date date){
		LocalDate now = date.toInstant().atZone( ZoneId.systemDefault()).toLocalDate();
		LocalDate lastDay = now.with( TemporalAdjusters.lastDayOfMonth());
		Date endTime = Date.from(lastDay.atStartOfDay( ZoneOffset.ofHours(8)).toInstant());
		SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
		try {
			return format.parse(new SimpleDateFormat("yyyyMMdd").format(endTime) + " 23:59:59");
		} catch (ParseException e) {
			e.printStackTrace();
		}
		throw new IllegalArgumentException("时间格式转换错误");
	}


	/**
	 * 获取年份
	 * @return
	 */
	public static int getSysYear() {
		Calendar date = Calendar.getInstance();
		return date.get(Calendar.YEAR);
	}

	/**
	 * 获取月份
	 * @return
	 */
	public static int getSysMonth() {
		Calendar date = Calendar.getInstance();
		return (date.get(Calendar.MONTH)+1);
	}

	/**
	 *  获取某一天在一年中的第几周(一周从周一计算)
	 * @param date  时间
	 * @return
	 */
	public static int getWeekNumOfYear(Date date){
		Calendar c = getFirstDayOfWeek(date);
		int year = c.get(Calendar.YEAR);
		int weekNum = c.get(Calendar.WEEK_OF_YEAR);
		c.add(Calendar.DAY_OF_YEAR,6);
		int yearT = c.get(Calendar.YEAR);
		if (year != yearT){
			return 1;
		}
		return weekNum;
	}

	/**
	 *  获取某一天的所在周的周一日历
	 * @param date 时间
	 * @return
	 */
	public static Calendar getFirstDayOfWeek(Date date){
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.DAY_OF_YEAR,-1);
		Integer dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
		Integer d =  dayOfWeek - 1;
		c.setTime(date);
		c.add(Calendar.DAY_OF_YEAR,-d);
		return c;
	}
	/**
	 * 判断是否过去的日期
	 */
	public static boolean isPastDate(Date pastDate){
		boolean flag = false;
		Date nowDate = new Date();
		flag = pastDate.before(nowDate);
		Date instance = getInstance(nowDate);
		if(pastDate.equals(instance)){
			return false;
		}
		return flag;
	}

	/**
	 * 格式化时间 秒为0
	 * @param now
	 * @return
	 */
	public static Date getInstance(Date now){
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(now);
		// 将时分秒,毫秒域清零
		cal1.set(Calendar.HOUR_OF_DAY, 0);
		cal1.set(Calendar.MINUTE, 0);
		cal1.set(Calendar.SECOND, 0);
		cal1.set(Calendar.MILLISECOND, 0);
		return cal1.getTime();
	}
}
